// Filename: pipelineCyclerTrivialImpl.I
// Created by:  drose (31Jan06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::Constructor
//       Access: Public
//  Description: 
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerTrivialImpl::
PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *) {
  // In the trivial implementation, a derived class (the
  // PipelineCycler template class) stores the CycleData object
  // directly within itself, and since we have no data members or
  // virtual functions, we get away with assuming the pointer is the
  // same as the 'this' pointer.

  // If this turns out not to be true on a particular platform, we
  // will have to store the pointer in this class, for a little bit of
  // extra overhead.
#ifdef SIMPLE_STRUCT_POINTERS
  nassertv(initial_data == (CycleData *)this);
#else
  _data = initial_data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::Copy Constructor
//       Access: Private
//  Description: 
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerTrivialImpl::
PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl &) {
  // The copy constructor for the PipelineCyclerTrivialImpl case
  // doesn't work.  Don't try to use it.  The PipelineCycler template
  // class is #ifdeffed appropriately to call the normal constructor
  // instead.
  nassertv(false);
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::Copy Assignment
//       Access: Private
//  Description: 
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
operator = (const PipelineCyclerTrivialImpl &) {
  // The copy assignment operator for the PipelineCyclerTrivialImpl
  // case doesn't work.  Don't try to use it.  The PipelineCycler
  // template class is #ifdeffed appropriately not to call this
  // method.
  nassertv(false);
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::Destructor
//       Access: Public
//  Description: 
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerTrivialImpl::
~PipelineCyclerTrivialImpl() {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::acquire
//       Access: Public
//  Description: Grabs an overall lock on the cycler.  Release it with
//               a call to release().  This lock should be held while
//               walking the list of stages.
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
acquire(Thread *) {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::release
//       Access: Public
//  Description: Release the overall lock on the cycler that was
//               grabbed via acquire().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
release() {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::read_unlocked
//       Access: Public
//  Description: Returns a const CycleData pointer, filled with the
//               data for the current stage of the pipeline as seen by
//               this thread.  No lock is made on the contents; there
//               is no guarantee that some other thread won't modify
//               this object's data while you are working on it.
//               (However, the data within the returned CycleData
//               object itself is safe from modification; if another
//               thread modifies the data, it will perform a
//               copy-on-write, and thereby change the pointer stored
//               within the object.)
////////////////////////////////////////////////////////////////////
INLINE const CycleData *PipelineCyclerTrivialImpl::
read_unlocked(Thread *) const {
#ifdef SIMPLE_STRUCT_POINTERS
  return (const CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::read
//       Access: Public
//  Description: Returns a const CycleData pointer, filled with the
//               data for the current stage of the pipeline as seen by
//               this thread.  This pointer should eventually be
//               released by calling release_read().
////////////////////////////////////////////////////////////////////
INLINE const CycleData *PipelineCyclerTrivialImpl::
read(Thread *) const {
#ifdef SIMPLE_STRUCT_POINTERS
  return (const CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::increment_read
//       Access: Public
//  Description: Increments the count on a pointer previously
//               retrieved by read(); now the pointer will need to be
//               released twice.
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
increment_read(const CycleData *) const {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::release_read
//       Access: Public
//  Description: Releases a pointer previously obtained via a call to
//               read().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
release_read(const CycleData *) const {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::write
//       Access: Public
//  Description: Returns a non-const CycleData pointer, filled with a
//               unique copy of the data for the current stage of the
//               pipeline as seen by this thread.  This pointer may
//               now be used to write to the data, and that copy of
//               the data will be propagated to all later stages of the
//               pipeline.  This pointer should eventually be released
//               by calling release_write().
//
//               There may only be one outstanding write pointer on a
//               given stage at a time, and if there is a write
//               pointer there may be no read pointers on the same
//               stage (but see elevate_read).
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
write(Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::write_upstream
//       Access: Public
//  Description: This special variant on write() will automatically
//               propagate changes back to upstream pipeline stages.
//               If force_to_0 is false, then it propagates back only
//               as long as the CycleData pointers are equivalent,
//               guaranteeing that it does not modify upstream data
//               (other than the modification that will be performed
//               by the code that returns this pointer).  This is
//               particularly appropriate for minor updates, where it
//               doesn't matter much if the update is lost, such as
//               storing a cached value.
//
//               If force_to_0 is trivial, then the CycleData pointer for
//               the current pipeline stage is propagated all the way
//               back up to stage 0; after this call, there will be
//               only one CycleData pointer that is duplicated in all
//               stages between stage 0 and the current stage.  This
//               may undo some recent changes that were made
//               independently at pipeline stage 0 (or any other
//               upstream stage).  However, it guarantees that the
//               change that is to be applied at this pipeline stage
//               will stick.  This is slightly dangerous because of
//               the risk of losing upstream changes; generally, this
//               should only be done when you are confident that there
//               are no upstream changes to be lost (for instance, for
//               an object that has been recently created).
////////////////////////////////////////////////////////////////////
CycleData *PipelineCyclerTrivialImpl::
write_upstream(bool, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::elevate_read
//       Access: Public
//  Description: Elevates a currently-held read pointer into a write
//               pointer.  This may or may not change the value of the
//               pointer.  It is only valid to do this if this is the
//               only currently-outstanding read pointer on the
//               current stage.
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
elevate_read(const CycleData *, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::elevate_read_upstream
//       Access: Public
//  Description: Elevates a currently-held read pointer into a write
//               pointer, like elevate_read(), but also propagates the
//               pointer back to upstream stages, like
//               write_upstream().
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
elevate_read_upstream(const CycleData *, bool, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::increment_write
//       Access: Public
//  Description: Increments the count on a pointer previously
//               retrieved by write(); now the pointer will need to be
//               released twice.
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
increment_write(CycleData *) const {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::release_write
//       Access: Public
//  Description: Releases a pointer previously obtained via a call to
//               write().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
release_write(CycleData *) {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::get_num_stages
//       Access: Public
//  Description: Returns the number of stages in the pipeline.
////////////////////////////////////////////////////////////////////
INLINE int PipelineCyclerTrivialImpl::
get_num_stages() {
  return 1;
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::read_stage_unlocked
//       Access: Public
//  Description: Returns a const CycleData pointer, filled with the
//               data for the indicated stage of the pipeline.  As in
//               read_unlocked(), no lock is held on the returned
//               pointer.
////////////////////////////////////////////////////////////////////
INLINE const CycleData *PipelineCyclerTrivialImpl::
read_stage_unlocked(int) const {
#ifdef SIMPLE_STRUCT_POINTERS
  return (const CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::read_stage
//       Access: Public
//  Description: Returns a const CycleData pointer, filled with the
//               data for the indicated pipeline stage.  This pointer
//               should eventually be released by calling
//               release_read().
////////////////////////////////////////////////////////////////////
INLINE const CycleData *PipelineCyclerTrivialImpl::
read_stage(int, Thread *) const {
#ifdef SIMPLE_STRUCT_POINTERS
  return (const CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::release_read_stage
//       Access: Public
//  Description: Releases a pointer previously obtained via a call to
//               read_stage().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
release_read_stage(int, const CycleData *) const {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::write_stage
//       Access: Public
//  Description: Returns a pointer suitable for writing to the nth
//               stage of the pipeline.  This is for special
//               applications that need to update the entire pipeline
//               at once (for instance, to remove an invalid pointer).
//               This pointer should later be released with
//               release_write_stage().
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
write_stage(int, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::write_stage_upstream
//       Access: Public
//  Description: Returns a pointer suitable for writing to the nth
//               stage of the pipeline.  This is for special
//               applications that need to update the entire pipeline
//               at once (for instance, to remove an invalid pointer).
//               This pointer should later be released with
//               release_write_stage().
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
write_stage_upstream(int, bool, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::elevate_read_stage
//       Access: Public
//  Description: Elevates a currently-held read pointer into a write
//               pointer.  This may or may not change the value of the
//               pointer.  It is only valid to do this if this is the
//               only currently-outstanding read pointer on the
//               current stage.
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
elevate_read_stage(int, const CycleData *, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::elevate_read_stage_upstream
//       Access: Public
//  Description: Elevates a currently-held read pointer into a write
//               pointer.  This may or may not change the value of the
//               pointer.  It is only valid to do this if this is the
//               only currently-outstanding read pointer on the
//               current stage.
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
elevate_read_stage_upstream(int, const CycleData *, bool, Thread *) {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::release_write_stage
//       Access: Public
//  Description: Releases a pointer previously obtained via a call to
//               write_stage().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerTrivialImpl::
release_write_stage(int, CycleData *) {
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::get_parent_type
//       Access: Public
//  Description: Returns the type of object that owns this cycler, as
//               reported by CycleData::get_parent_type().
////////////////////////////////////////////////////////////////////
INLINE TypeHandle PipelineCyclerTrivialImpl::
get_parent_type() const {
  return cheat()->get_parent_type();
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::cheat
//       Access: Public
//  Description: Returns a pointer without counting it.  This is only
//               intended for use as the return value for certain
//               nassertr() functions, so the application can recover
//               after a failure to manage the read and write pointers
//               correctly.  You should never call this function
//               directly.
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerTrivialImpl::
cheat() const {
#ifdef SIMPLE_STRUCT_POINTERS
  return (CycleData *)this;
#else
  return _data;
#endif  // SIMPLE_STRUCT_POINTERS
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::get_read_count
//       Access: Public
//  Description: Returns the number of handles currently outstanding
//               to read the current stage of the data.  This should
//               only be used for debugging purposes.
////////////////////////////////////////////////////////////////////
INLINE int PipelineCyclerTrivialImpl::
get_read_count() const {
  return 0;
}

////////////////////////////////////////////////////////////////////
//     Function: PipelineCyclerTrivialImpl::get_write_count
//       Access: Public
//  Description: Returns the number of handles currently outstanding
//               to read the current stage of the data.  This will
//               normally only be either 0 or 1.  This should only be
//               used for debugging purposes.
////////////////////////////////////////////////////////////////////
INLINE int PipelineCyclerTrivialImpl::
get_write_count() const {
  return 0;
}

